//********************************************************************************************************************//
//ORGANIZATION:
//AUTHOR: bpeng(bogers.peng@gmail.com)
//SUMMARY:
//********************************************************************************************************************//
#include "../Atom.h"

using namespace Native::System;
//********************************************************************************************************************//
//UString
//********************************************************************************************************************//
wstring UString::ToWideString(MSTRING& input, bool appended)
{
    size_t input_length = input.length();
    wstring output = EMPTY_STRING;

    if (input_length > 0) {
        size_t offset = 0;

        while (offset < input_length) {
            wchar_t cstring[BUFFER_SIZE+1] = {0};

            size_t converted_length = mbstowcs(cstring, input.c_str() + offset, BUFFER_SIZE);
            if (converted_length == -1) {
                return EMPTY_STRING;
            }

            offset += converted_length;

            cstring[converted_length] = L'\0';

            output.append(cstring);
        }
    }

    return output;
}

mstring UString::ToMultipleString(WSTRING& input, bool appended)
{
    size_t input_length = input.length();
    mstring output = "";

    if (input_length > 0) {
        size_t offset = 0;

        while (offset < input_length) {
            char cstring[BUFFER_SIZE+1] = {0};
            size_t converted_characters = wcstombs(cstring, input.c_str()+offset, BUFFER_SIZE);

            if (converted_characters == -1) {
                return "";
            }

            offset += converted_characters;

            cstring[converted_characters] = L'\0';

            output.append(cstring);
        }
    }

    return output;
}

vector<wstring> UString::Split(WSTRING& input, wchar_t separator)
{
    wstring operation(input);
    vector<wstring> strings;
    size_t index;

    while ((index = operation.find(separator)) != -1) {
        strings.push_back(operation.substr(0, index));

        operation = operation.substr(index+1, operation.length());
    }

    if (operation.length() > 0) {
        strings.push_back(operation);
    }

    return move(strings);
}

wstring UString::ToLower(WSTRING& input)
{
    wstring result = input;

    transform(result.begin(), result.end(), result.begin(), tolower);

    return move(result);
}

wstring UString::ToUpper(WSTRING& input)
{
    wstring result = input;

    transform(result.begin(), result.end(), result.begin(), toupper);

    return move(result);
}

//********************************************************************************************************************//
//UNumeric
//********************************************************************************************************************//
wstring _TrimHexString(WSTRING& hexadecimal_string, size_t number_of_bytes)
{
    if (hexadecimal_string.length() > 0 && number_of_bytes > 0) {
        return hexadecimal_string.substr(hexadecimal_string.length()-number_of_bytes*2, number_of_bytes*2);
    } else {
        return L"";
    }
}

wstring UNumeric::ToString(uint8_t numeric, EBase base)
{
    wstring result;

    switch(base)
    {
    case BASE_DECIMAL:
        {
            wchar_t cstring[MAX_DECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%u", numeric);
            result = cstring;
        }
        break;
    case BASE_HEXADECIMAL:
        {
            wchar_t cstring[MAX_HEXADECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%02X", numeric);
            result = _TrimHexString(cstring, BYTE8_SIZE);
        }
        break;
    }

    return move(result);
}

wstring UNumeric::ToString(int8_t numeric, EBase base)
{
    wstring result;

    switch(base)
    {
    case BASE_DECIMAL:
        {
            wchar_t cstring[MAX_DECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%d", numeric);
            result = cstring;
        }
        break;
    case BASE_HEXADECIMAL:
        {
            wchar_t cstring[MAX_HEXADECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%02X", numeric);
            result = _TrimHexString(cstring, BYTE8_SIZE);
        }
        break;
    }

    return move(result);
}

wstring UNumeric::ToString(uint16_t numeric, EBase base)
{
    wstring result;

    switch(base)
    {
    case BASE_DECIMAL:
        {
            wchar_t cstring[MAX_DECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%u", numeric);
            result = cstring;
        }
        break;
    case BASE_HEXADECIMAL: 
        {
            wchar_t cstring[MAX_HEXADECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%04X", numeric);
            result = _TrimHexString(cstring, BYTE16_SIZE);
        }
        break;
    }

    return move(result);
}

wstring UNumeric::ToString(int16_t numeric, EBase base)
{
    wstring result;

    switch(base)
    {
    case BASE_DECIMAL:
        {
            wchar_t cstring[MAX_DECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%d", numeric);
            result = cstring;
        }
        break;
    case BASE_HEXADECIMAL:
        {
            wchar_t cstring[MAX_HEXADECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%04X", numeric);
            result = _TrimHexString(cstring, BYTE16_SIZE);
        }
        break;
    }

    return move(result);
}

wstring UNumeric::ToString(uint32_t numeric, EBase base)
{
    wstring result;

    switch(base)
    {
    case BASE_DECIMAL:
        {
            wchar_t cstring[MAX_DECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%u", numeric);
            result = cstring;
        }
        break;
    case BASE_HEXADECIMAL:
        {
            wchar_t cstring[MAX_HEXADECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%08X", numeric);
            result = _TrimHexString(cstring, BYTE32_SIZE);
        }
        break;
    }

    return move(result);
}

wstring UNumeric::ToString(int32_t numeric, EBase base)
{
    wstring result;

    switch(base)
    {
    case BASE_DECIMAL:
        {
            wchar_t cstring[MAX_DECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%d", numeric);
            result = cstring;
        }
        break;
    case BASE_HEXADECIMAL:
        {
            wchar_t cstring[MAX_HEXADECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%08X", numeric);
            result = _TrimHexString(cstring, BYTE32_SIZE);
        }
        break;
    }

    return move(result);
}

wstring UNumeric::ToString(uint64_t numeric, EBase base)
{
    wstring result;

    switch(base)
    {
    case BASE_DECIMAL:
        {
            wchar_t cstring[MAX_DECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%llu", numeric);
            result = cstring;
        }
        break;
    case BASE_HEXADECIMAL:
        {
            wchar_t cstring[MAX_HEXADECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%016llX", numeric);
            result = _TrimHexString(cstring, BYTE64_SIZE);
        }
        break;
    }

    return move(result);
}

wstring UNumeric::ToString(int64_t numeric, EBase base)
{
    wstring result;

    switch(base)
    {
    case BASE_DECIMAL:
        {
            wchar_t cstring[MAX_DECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%lld", numeric);
            result = cstring;
        }
        break;
    case BASE_HEXADECIMAL:
        {
            wchar_t cstring[MAX_HEXADECIMAL_LENGTH+1] = {0};

            swprintf(cstring, L"%016llX", numeric);
            result = _TrimHexString(cstring, BYTE64_SIZE);
        }
        break;
    }

    return move(result);
}

wstring UBool::ToString(bool value)
{
    return value? L"True" : L"False";
}